package com.moore.service.Impl;

import com.moore.bean.Allocation;
import com.moore.bean.Apartment;
import com.moore.bean.Message;
import com.moore.bean.TenantInfo;
import com.moore.dto.ResponseData;
import com.moore.mapper.AuditMapper;
import com.moore.service.AuditService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.moore.utils.Logger.toLog;

@Service
public class AuditServiceImpl implements AuditService {
    @Autowired
    AuditMapper auditMapper;

    private static final List<String> priority = Arrays.asList("A", "B", "C", "D");

    @Override
    public ResponseData getAuditList(TenantInfo tenantInfo) {
        List<TenantInfo> tenantInfoList = auditMapper.getAuditList(tenantInfo);
        toLog("获取成功");
        return new ResponseData(200, "获取成功", tenantInfoList, auditMapper.getAuditCount(tenantInfo));
    }

    @Override
    public ResponseData auditTenant(List<TenantInfo> tenantInfoList) {
        List<Message> messages = new ArrayList<>();
        for (TenantInfo tenantInfo : tenantInfoList) {
            if ("保存".equals(tenantInfo.getStatus())) {
                toLog(tenantInfo.getRealName() + "审核被拒，拒绝理由: " + tenantInfo.getReason());
                messages.add(new Message(
                        tenantInfo.getTenant(),
                        "拒绝",
                        "审核失败提醒",
                        "尊敬的" + tenantInfo.getRealName() + "，您提交的资料未通过审核，原因为" + tenantInfo.getReason() + "，请重新提交资料",
                        "资格审核员",
                        "未读"));

            } else if ("已审核".equals(tenantInfo.getStatus())) {
                toLog(tenantInfo.getRealName() + "审核通过");
                messages.add(new Message(
                        tenantInfo.getTenant(),
                        "同意",
                        "审核通过提醒",
                        "尊敬的" + tenantInfo.getRealName() + "，您提交的资料已通过审核，我们将于5个工作日内为您分配套房，请留意站内消息",
                        "资格审核员",
                        "未读"));
            }
        }
        int result = auditMapper.insertMessage(messages);
        int result1 = auditMapper.updateTenant(tenantInfoList);
        if (result1 > 0 && result > 0) {
            toLog("审核成功");
            return new ResponseData(200, "审核成功", null, 0);
        } else {
            toLog("审核失败");
            return new ResponseData(500, "审核失败", null, 0);
        }
    }

    @Override
    public ResponseData allocateApartment(TenantInfo tenantInfo, Apartment apartment) {
        toLog("正在校验分配");
        String message;
        if (tenantInfo == null || apartment == null) {
            message = "输入无效，请检查申请人和房屋信息";
            toLog(message);
            return new ResponseData(500, message, null, 0);
        }
        // 家庭成员数量和对应的最大面积限制
        int[] familySizes = {3, 4, 5, 6};
        int[] maxAreas = {35, 50, 70, 80};
        for (int i = 0; i < familySizes.length; i++) {
            if (tenantInfo.getFamilySize() <= familySizes[i] && apartment.getArea() > maxAreas[i]) {
                message = String.format("很抱歉，家庭成员在%d人或%d人以内，只能分配%d平方米或以下的套房。", familySizes[i], familySizes[i], maxAreas[i]);
                toLog(message);
                return new ResponseData(500, message, null, 0);
            }
        }
        if (apartment.getArea() > 80) {
            message = "很抱歉，公租房不能出现80平方米以上的套房";
            toLog(message);
            return new ResponseData(500, message, null, 0);
        }
        // 检查是否已经分配
        if (apartment.isAllocated() || apartment.getStatus().equals("已分配")) {
            message = "该套房已经分配给其他申请人，请选择其他房源";
            toLog(message);
            return new ResponseData(500, message, null, 0);
        }
        if (tenantInfo.isAllocated() || tenantInfo.getStatus().equals("已分配")) {
            message = "该申请人已经分配了其他套房，请检查申请信息";
            toLog(message);
            return new ResponseData(500, message, null, 0);
        }
        toLog("校验通过，正在分配");
        return new ResponseData(200, "分配成功", null, 0);
    }

    @Override
    public ResponseData allocateApartments(List<TenantInfo> tenants) {
        toLog("正在自动随机分配套房");
        // 获取可用的套房
        List<Apartment> availableApartments = auditMapper.getApartments().stream()
                .filter(apt -> "已发布".equals(apt.getStatus()) || "待分配".equals(apt.getStatus()))
                .collect(Collectors.toList());
        // 根据保护类型和ID对租户进行排序
        tenants.sort(Comparator.comparing(TenantInfo::getProtectionType, Comparator.comparingInt(priority::indexOf))
                .thenComparingLong(TenantInfo::getId));
        // 初始化分配、消息和套房列表
        List<Allocation> allocations = new ArrayList<>();
        List<Message> messages = new ArrayList<>();
        List<Apartment> apartments = new ArrayList<>();
        StringBuilder info = new StringBuilder();
        // 按区域将可用套房分组
        Map<String, List<Apartment>> apartmentsByArea = availableApartments.stream()
                .collect(Collectors.groupingBy(Apartment::getAreaName));
        // 对每个租客进行套房分配
        for (TenantInfo tenant : tenants) {
            boolean allocated = false; // 标记是否成功分配
            List<Apartment> areaApartments = apartmentsByArea.getOrDefault(tenant.getRequestedArea(), new ArrayList<>());
            for (Iterator<Apartment> iterator = areaApartments.iterator(); iterator.hasNext(); ) {
                Apartment apt = iterator.next();
                if (isSuitable(apt, tenant)) {
                    // 分配套房
                    allocateApartment(apt, tenant, allocations, messages, apartments);
                    iterator.remove(); // 确保套房不会重复分配
                    allocated = true;
                    info.append("租客").append(tenant.getRealName()).append("已成功分配到").append(apt.getAreaName()).append(apt.getCommunityName()).append("的").append(apt.getRoomNumber()).append("号房\n");
                    break;
                }
            }
            if (!allocated) {
                // 未找到合适的套房
                toLog("未找到合适的套房！租客" + tenant.getRealName() + "未能分配到套房");
                info.append("租客").append(tenant.getRealName()).append("未能分配到套房\n");
            }
        }
        // 插入分配结果并返回响应
        ResponseData response = insertParameter(tenants, apartments, messages, allocations, info.toString());
        if (response.getCode() == 200) {
            toLog("所有租客分配完成！");
        }
        return response;
    }

    private void allocateApartment(Apartment apt, TenantInfo tenant, List<Allocation> allocations, List<Message> messages, List<Apartment> apartments) {
        // 更新套房和租客状态，并记录分配信息
        apt.setStatus("已分配");
        apartments.add(apt);
        tenant.setStatus("已分配");
        allocations.add(new Allocation(apt.getId(), tenant.getId(), "已分配"));
        toLog("分配成功！租客" + tenant.getRealName() + "已成功分配到" + apt.getAreaName() + apt.getCommunityName() + "的" + apt.getRoomNumber() + "号房");
        String msg = createMessage(tenant, apt);
        messages.add(new Message(tenant.getTenant(), "分配", "套房分配成功", msg, "资格审核员", "未读"));
    }

    private String createMessage(TenantInfo tenant, Apartment apt) {
        // 创建分配成功的消息内容
        return String.format("尊敬的%s，您已成功的被分配到%s%s的%s号房，请于7个工作日内前往下方链接填写合同，逾期套房将被回收，敬请留意！",
                tenant.getRealName(), apt.getAreaName(), apt.getCommunityName(), apt.getRoomNumber());
    }

    @Override
    public ResponseData allocateSave(List<TenantInfo> tenants, List<Apartment> apartments) {
        toLog("正在保存已分配套房");
        // 初始化分配、消息和套房列表
        List<TenantInfo> allocateTenants = new ArrayList<>();
        List<Apartment> allocateApartments = new ArrayList<>();
        List<Allocation> allocations = new ArrayList<>();
        List<Message> messages = new ArrayList<>();
        // 对每个租客进行套房保存
        for (TenantInfo tenant : tenants) {
            for (Apartment apt : apartments) {
                if (apt.getRoomNumber().equals(tenant.getAssignedApartment())) {
                    // 分配套房
                    allocateApartment(apt, tenant, allocations, messages, allocateApartments);
                    allocateTenants.add(tenant);
                    break;
                }
            }
        }
        return insertParameter(allocateTenants, allocateApartments, messages, allocations,"保存成功");
    }

    private ResponseData insertParameter(List<TenantInfo> tenants, List<Apartment> apartments, List<Message> messages, List<Allocation> allocations, String info) {
        // 更新数据库中的套房、租客、消息和分配记录
        int apartmentRes = auditMapper.updateApartment(apartments);
        int tenantRes = auditMapper.updateTenant(tenants);
        int messageRes = auditMapper.insertMessage(messages);
        int allocationRes = auditMapper.insertAllocation(allocations);
        // 检查更新结果并返回响应
        if (apartmentRes == 0) return new ResponseData(500, "套房修改失败", null, 0);
        if (tenantRes == 0) return new ResponseData(500, "租客修改失败", null, 0);
        if (messageRes == 0) return new ResponseData(500, "消息插入失败", null, 0);
        if (allocationRes == 0) return new ResponseData(500, "分配记录插入失败", null, 0);
        return new ResponseData(200, info, null, 0);
    }

    private static boolean isSuitable(Apartment apt, TenantInfo tenants) {
        if (tenants.getFamilySize() <= 3 && apt.getArea() <= 35) return true;
        if (tenants.getFamilySize() <= 4 && apt.getArea() <= 50) return true;
        if (tenants.getFamilySize() <= 5 && apt.getArea() <= 70) return true;
        return tenants.getFamilySize() <= 6 && apt.getArea() <= 80;
    }
}